package com.cneport.das.client.param;

import com.cneport.das.client.conf.ClientConfCache;
import com.cneport.das.client.conf.TransConf;
import com.cneport.das.common.model.param.ClientRequest;
import com.cneport.das.common.model.param.ClientResponse;
import com.cneport.das.common.model.param.ErpRequest;
import com.cneport.das.common.model.param.ErpResponse;
import com.cneport.das.common.utils.*;
import com.cneport.das.common.validate.FieldCheckUtil;
import com.cneport.das.common.validate.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;

import static com.cneport.das.common.utils.EncryptUtil.encode;

/**
 * @Desc 参数服务客户端
 * @Ver 1.0
 * @Author GavinZhang
 * @Company 东方物通科技有限（北京）公司
 * @Date 2021-12-14 10:24:05
 */
@RestController
@Slf4j
public class ParamClientController {

    @Autowired
    private ClientConfCache clientConfCache;

    @Autowired
    private BizRecorder bizRecorder;


    /**
     * 进行换参
     *
     * @param erpRequest
     * @return
     */
    private ClientRequest exchangeReq(ErpRequest erpRequest) {
        ErpRequest.GetReq getReq = erpRequest.getGetReq();
        String guid = getReq.getGuid();
        bizRecorder.write("param-req", guid, JAXBUtils.obj2Xml(erpRequest));
        String copNo = getReq.getCopNo();
        TransConf conf = clientConfCache.getTransConfigByCorpNo(copNo);
        if (conf == null) {
            log.error("copNo 为" + copNo + "的企业客户端配置信息不存在！");
            fail(guid, "-1", "copNo 为" + copNo + "的企业客户端配置信息不存在！");
        }


        String corpLic = conf.getLicence() == null ? "" : conf.getLicence();
        String p = clientConfCache.getPriEncoderPath(copNo);
        String type = getReq.getParaType();
        String code = getReq.getParaInfo();

        ClientRequest clientRequest = new ClientRequest();
        ClientRequest.QryReq qryReq = ClientRequest.QryReq.builder()
                .guid(getReq.getGuid())
                .reqTime(DateUtil.C14())
                .copLic(corpLic)
                .encoderVer(conf.getEncoderVer())
                .paraType(type)
                .paraInfo(code)
                .copNo(copNo)
                .build();
        clientRequest.setQryReq(qryReq);

        //加密
        ClientRequest encode = encode(clientRequest, p, true);
        //加签
        clientRequest = SignUtil.sign(encode);
        return clientRequest;
    }

    /**
     * 返回值进行转换
     *
     * @param clientResponse
     * @return
     */
    private String exchangeRetn(ClientResponse clientResponse, String copNo, long start) {

        ClientResponse.QryRetn qryRetn = clientResponse.getQryRetn();
        String guid = qryRetn.getGuid();
        String code = qryRetn.getRespCode();
        String errorMsg = qryRetn.getRespInfo();
        //若返回失败，不做任何返回值的解析
        if (!code.equals("0")) {
            return fail(guid, code, errorMsg);
        }


        //验签
        boolean pass = SignUtil.check(clientResponse);
        if (!pass) {
            return fail(guid, "-1", "验签不通透！");
        }

        //解密
        String p = clientConfCache.getPriEncoderPath(copNo);
        clientResponse = EncryptUtil.decode(clientResponse, p, true);
        bizRecorder.write("param-resp", guid, JAXBUtils.obj2Xml(clientResponse));
        ErpResponse response = new ErpResponse();

        ErpResponse.ErpGetRetn.ErpGetRetnBuilder erpGetRetn = ErpResponse.ErpGetRetn.builder();
        erpGetRetn.respTime(DateUtil.C14()).dealTime(System.currentTimeMillis() - start).guid(guid).paraType(clientResponse.getQryRetn().getParaType()).respCode("0").respInfo("");
        response.setRetHead(erpGetRetn.build());

        ClientResponse.BizData bizData = clientResponse.getBizData();
        response.setBizData(new ErpResponse.ErpBizData(bizData.getDataForm(), bizData.getData()));

        return JAXBUtils.obj2Xml(response);
    }


    /**
     * 向客户端请求查询参数
     *
     * @param req
     * @return
     */
    @PostMapping("/getClientParam")
    public String erpGetParam(@RequestBody String req) {

        long start = System.currentTimeMillis();

        ErpRequest request = JAXBUtils.xml2Obj(ErpRequest.class, req);
        //格式校验
        ResultVO validate = FieldCheckUtil.validate(request, null);
        if (!validate.isSuccess()) {
            return fail(request.getGetReq().getGuid(), "-1", validate.getErrorStr());
        }

        String url = clientConfCache.getServerServiceUrl();
        if (StringUtil.isBlank(url)) {
            return fail(request.getGetReq().getGuid(), "-1", "das.client.serverService.url 配置为空！");
        } else {
            url = url + "/queryServerParam";
        }
        try {
            ClientRequest clientRequest = exchangeReq(request);
            String corpNo = clientRequest.getQryReq().getCopNo();
            String param = JAXBUtils.obj2Xml(clientRequest).trim();
            try {
                String str = Base64Utils.encodeToUrlSafeString(param.getBytes(StandardCharsets.UTF_8));
                String result = HttpUtils.post(url, str, new HashMap());
                ClientResponse response = JAXBUtils.xml2Obj(ClientResponse.class, result);
                String resp = exchangeRetn(response, corpNo, start);
                return resp;
            } catch (Exception e) {
                e.printStackTrace();
                return fail(clientRequest.getQryReq().getGuid(), "-1", e.getLocalizedMessage());
            }
        } catch (Exception e) {
            return fail(request.getGetReq().getGuid(), "-1", e.getLocalizedMessage());
        }


    }


    private String fail(String guid, String code, String msg) {
        ErpResponse response = new ErpResponse();
        ErpResponse.ErpGetRetn getRetn = ErpResponse.ErpGetRetn.builder()
                .guid(guid)
                .respCode(code)
                .respInfo(msg)
                .respTime(DateUtil.C14())
                .build();
        response.setRetHead(getRetn);
        return JAXBUtils.obj2Xml(response);
    }


}
